package com.glkj.vipsystem.modules.cash.controller;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.glkj.vipsystem.common.utils.Constant;
import com.glkj.vipsystem.common.utils.PageUtils;
import com.glkj.vipsystem.common.utils.Query;
import com.glkj.vipsystem.common.utils.R;
import com.glkj.vipsystem.common.validator.ValidatorUtils;
import com.glkj.vipsystem.entity.ao.*;
import com.glkj.vipsystem.entity.gen.KaidanUser;
import com.glkj.vipsystem.modules.cash.form.CashForm;
import com.glkj.vipsystem.modules.sys.controller.AbstractController;
import com.glkj.vipsystem.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;

/**
 * 收银订单控制器
 *
 * @author LiMuchan
 */
@RestController
@RequestMapping("/cash/order")
public class OrderController extends AbstractController {

    @Resource
    private IOrderService orderService;
    @Resource
    private IShopService shopService;
    @Resource
    private ICompanyService companyService;
    @Resource
    private IEmployeeService employeeService;
    @Resource
    private IGoodsService goodsService;
    @Resource
    private IVipCardService vipCardService;
    @Resource
    private IOrderGoodsService orderGoodsService;
    @Resource
    private IKaidanUserService kaidanUserService;

    /**
     * 列表
     */
    @RequestMapping(value = "/list")
    @RequiresPermissions({"cash:order:list"})
    public R list(@RequestParam Map<String, Object> params) {
        Wrapper<OrderAO> wrapper = getWrapper(params);
        wrapper.orderBy("id desc");
        Page<OrderAO> page = orderService.selectPage(
                new Query<OrderAO>(params).getPage(), wrapper
        );
        List<OrderAO> records = page.getRecords();
        if (!CollectionUtils.isEmpty(records)) {
            for (OrderAO record : records) {
                Integer kaidanUserId = record.getKaidanUserId();
                if (kaidanUserId != null) {
                    KaidanUser kaidanUser = kaidanUserService.selectById(kaidanUserId);
                    record.setKaidanUser(kaidanUser);
                }
            }
        }
        return R.ok().put("page", new PageUtils(page));
    }

    /**
     * 数据统计
     */
    @RequestMapping(value = "/getData")
    @RequiresPermissions({"cash:order:list"})
    public R getData(@RequestParam Map<String, Object> params) {
        Wrapper<OrderAO> wrapper = getWrapper(params);
        wrapper.setSqlSelect("count(*) as orderNum, sum(order_amount) as orderAmount,sum(pay_amount) as payAmount");
        Map<String, Object> data = orderService.selectMap(wrapper);
        if (data == null) {
            data = new HashMap<>();
        }
        data.putIfAbsent("orderNum", 0);
        data.putIfAbsent("orderAmount", 0);
        data.putIfAbsent("payAmount", 0);
        return R.ok().put("data", data);
    }

    private Wrapper<OrderAO> getWrapper(Map<String, Object> params) {
        Wrapper<OrderAO> wrapper = new EntityWrapper<>();
        String memberMobile = (String) params.get("memberMobile");
        String time = (String) params.get("time");
        String shopName = (String) params.get("shopName");
        String operator = (String) params.get("operator");
        String sn = (String) params.get("sn");
        String vipCardType = (String) params.get("vipCardType");
        String vipCardNo = (String) params.get("vipCardNo");
        String kaidanUser = (String) params.get("kaidanUser");
        if (checkString(memberMobile)) {
            wrapper.like("member_mobile", memberMobile);
        }
        if (checkString(time) && time.contains("~")) {
            String[] timeRange = time.split("~");
            wrapper.ge("create_time", timeRange[0].trim());
            wrapper.le("create_time", timeRange[1].trim() + " 23:59:59");
        }
        if (checkString(shopName)) {
            wrapper.like("shop_name", shopName);
        }
        if (checkString(operator)) {
            wrapper.like("operator", operator);
        }
        if (checkString(sn)) {
            wrapper.like("sn", sn);
        }
        if (checkString(vipCardType)) {
            wrapper.eq("vip_card_type", vipCardType);
        }
        if (checkString(vipCardNo)) {
            wrapper.like("vip_card_no", vipCardNo);
        }
        if (checkString(kaidanUser)) {
            wrapper.where("kaidan_user_id in (select id from t_kaidan_user where name like '%" + kaidanUser + "%'" +
                    " or mobile like '%" + kaidanUser + "%')");
        }

        String username = getUser().getUsername();
        // 数据权限控制
        if (isCompanyRole()) {
            // 公司管理员
            wrapper.where("company_id = (select id from t_company where `username` = '" + username + "')");
        } else if (isEmployeeRole()) {
            wrapper.where("shop_id = (select shop_id from t_employee where `username` = '" + username + "')");
        }

        return wrapper;
    }

    private static boolean checkString(String str) {
        return StringUtils.isNotBlank(str) && !str.equals("undefined") && !str.equals("null");
    }

    /**
     * 导出收银订单记录
     */
    @GetMapping(value = "/export")
    public R export(@RequestParam Map<String, Object> params, HttpServletResponse response) {
        String time = (String) params.get("time");
        if (StringUtils.isBlank(time) || !time.contains("~")) {
            return R.error("请选择收银时间范围");
        }
        // 校验时间范围 范围最多30天
        String[] timeRange = time.split("~");
        Date start = DateUtil.parseDate(timeRange[0].trim());
        Date end = DateUtil.parseDate(timeRange[1].trim());
        if ((end.getTime() - start.getTime()) > 31L * 24 * 3600 * 1000) {
            return R.error("时间范围最大只能一个月");
        }

        Wrapper<OrderAO> wrapper = getWrapper(params);
        wrapper.orderBy("id desc");

        TemplateExportParams excelParams = new TemplateExportParams(
                "excel/cash_order.xlsx"
        );
        Map<String, Object> map = new HashMap<>();
        map.put("exportTime", DateUtil.format(new Date(), "yyyy/MM/dd HH:mm:ss"));
        // 封装excel模板收银订单记录数据
//        List<Map<String, String>> listMap = new ArrayList<>();
        List<OrderAO> orderAOS = this.orderService.selectList(wrapper);
        map.put("maplist", orderAOS);
        Workbook workbook = ExcelExportUtil.exportExcel(excelParams, map);
        try {
            // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码
            String fileName = URLEncoder.encode("收银订单记录", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            ServletOutputStream os = response.getOutputStream();
            workbook.write(os);
            os.flush();
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("导出失败：" + e.getMessage());
        }

        return null;
    }

    /**
     * 详情
     */
    @RequestMapping(value = "/detail/{id}")
    @RequiresPermissions({"cash:order:list"})
    public R detail(@PathVariable("id") Long id) {
        OrderAO orderAO = orderService.selectById(id);
        Integer kaidanUserId = orderAO.getKaidanUserId();
        if (kaidanUserId != null) {
            KaidanUser kaidanUser = kaidanUserService.selectById(kaidanUserId);
            orderAO.setKaidanUser(kaidanUser);
        }
        Map<String, Object> data = new HashMap<>();
        data.put("order", orderAO);
        List<OrderGoodsAO> list = orderGoodsService.selectList(
                new EntityWrapper<OrderGoodsAO>()
                        .eq("order_id", id)
        );
        data.put("goodsList", list);
        return R.ok().put("data", data);
    }

    /**
     * 新增收银订单
     */
    @RequestMapping(value = "/save")
    @RequiresPermissions({"cash:order:list"})
    public R save(@RequestBody CashForm form) {
        ValidatorUtils.validateEntity(form);
        // 各种校验
        Integer shopId = form.getShopId();
        ShopAO shopAO = shopService.selectById(shopId);
        if (shopAO == null) {
            return R.error("店铺不存");
        }
        // 权限校验
        String username = getUser().getUsername();
        if (isCompanyRole()) {
            int selectCount = companyService.selectCount(
                    new EntityWrapper<CompanyAO>()
                            .eq("username", username)
                            .eq("id", shopAO.getCompanyId())
            );
            if (selectCount == 0) {
                return R.error("无操作权限");
            }
        } else if (isEmployeeRole()) {
            EmployeeAO employeeAO = employeeService.selectByUsername(username);
            if (employeeAO.getShopId().compareTo(shopId) != 0) {
                return R.error("无操作权限");
            }
        } else {
            return R.error("无操作权限");
        }
        List<GoodsAO> goodsList = form.getGoodsList();
        int size = goodsList.size();
        if (size == 0) {
            return R.error("请添加商品");
        }
        VipCardAO vipCard = form.getVipCard();
        // 不是散客 校验会员卡真实性
        if (vipCard.getCardType() != Constant.VipCardType.SANKE.getValue()) {
            Integer vipCardId = vipCard.getId();
            vipCard = vipCardService.selectById(vipCardId);
            if (vipCard == null) {
                return R.error("会员卡不存在");
            } else if (vipCard.getCompanyId().compareTo(shopAO.getCompanyId()) != 0) {
                return R.error("该会员卡不可在该公司使用");
            }
            form.setVipCard(vipCard);
        }
        BigDecimal orderAmount = new BigDecimal("0");
        for (GoodsAO goodsAO : goodsList) {
            if (goodsAO == null || goodsAO.getId() == null) {
                return R.error("商品数据错误");
            }
            GoodsAO selectOne = goodsService.selectOne(
                    new EntityWrapper<GoodsAO>()
                            .setSqlSelect("*,(select cat_name from t_goods_cat where id = t_goods.cat_id) as cat_name")
                            .eq("id", goodsAO.getId())
            );
            if (selectOne == null) {
                return R.error("商品不存在");
            }
            if (goodsAO.getNum() <= 0) {
                return R.error(String.format("商品[%s]数量必须大于0", selectOne.getGoodsName()));
            }
            if (!selectOne.getCardType().contains(vipCard.getCardType() + "")) {
                return R.error(String.format("商品[%s]不能用该会员卡消费", selectOne.getGoodsName()));
            }
            goodsAO.setCatName(selectOne.getCatName());
            goodsAO.setCatId(selectOne.getCatId());
            goodsAO.setGoodsUnit(selectOne.getGoodsUnit());
            goodsAO.setCardType(selectOne.getCardType());
            goodsAO.setGoodsName(selectOne.getGoodsName());
            orderAmount = orderAmount.add(goodsAO.getDiscountPrice().multiply(new BigDecimal(goodsAO.getNum() + "")));
        }

        // 插入订单
        form.setCompanyId(shopAO.getCompanyId());
        CompanyAO companyAO = companyService.selectById(shopAO.getCompanyId());
        form.setCompanyName(companyAO.getCompanyName());
        form.setShopName(shopAO.getShopName());
        form.setOperator(getOperator());
        form.setOrderAmount(orderAmount);
        orderService.save(form);
        return R.ok();
    }

    /**
     * 删除
     */
//    @RequestMapping(value = "/delete")
//    @RequiresPermissions({"cash:order:delete"})
//    public R delete(@RequestBody Long[] ids) {
//        if (ids != null && ids.length > 0) {
//            orderService.deleteBatchIds(Arrays.asList(ids));
//        }
//        return R.ok();
//    }

    /**
     * 获取当前登录用户的信息
     */
    @RequestMapping(value = "/getUserInfo")
    @RequiresPermissions({"cash:order:list"})
    public R getUserInfo() {
        String username = getOperator();
        return R.ok().put("data", username);
    }

    /**
     * 获取操作员信息
     *
     * @return 操作员信息
     */
    private String getOperator() {
        String username = getUser().getUsername();
        if (isCompanyRole()) {
            // 公司管理员
            CompanyAO companyAO = companyService.selectOne(new EntityWrapper<CompanyAO>().eq("username", username));
            if (companyAO != null) {
                username = companyAO.getManagerName() + "-" + companyAO.getManagerMobile();
            }
        } else if (isEmployeeRole()) {
            EmployeeAO employeeAO = employeeService.selectByUsername(username);
            if (employeeAO != null) {
                username = employeeAO.getEmployeeName() + "-" + employeeAO.getEmployeeMobile();
            }
        }
        return username;
    }

    /**
     * 获取当前登录用户的店铺
     */
    @RequestMapping(value = "/getShops")
    @RequiresPermissions({"cash:order:list"})
    public R getShops() {
        Wrapper<ShopAO> wrapper = new EntityWrapper<>();
        wrapper.orderBy("id desc");
        String username = getUser().getUsername();
        if (isCompanyRole()) {
            // 公司管理员
            wrapper.where("company_id = (select id from t_company where username = '" + username + "')");
        } else if (isEmployeeRole()) {
            wrapper.where("id = (select shop_id from t_employee where username = '" + username + "')");
        } else {
            return R.ok().put("data", new ArrayList<>());
        }
        List<ShopAO> list = shopService.selectList(wrapper);
        return R.ok().put("data", list);
    }

    /**
     * 获取最新的订单号
     */
    @RequestMapping(value = "/newOrderSn")
    @RequiresPermissions({"cash:order:list"})
    public R newOrderSn() {
        // 当前时间戳加上两位随机数 暂时不校验唯一性 保存进数据库再做校验
        String sn = DateUtil.format(new Date(), "yyyyMMddHHmmssSSS") + RandomUtil.randomNumbers(2);
        return R.ok().put("data", sn);
    }
}
